package com.train.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.train.common.enums.impl.BizExceptionEnums;
import com.train.common.exception.GlobalException;
import com.train.common.resp.CommonResp;
import com.train.common.resp.PageResp;
import com.train.common.utils.exception.ExceptionUtils;
import com.train.system.enums.impl.SeatColEnums;
import com.train.system.enums.impl.TrainTypeEnums;
import com.train.system.resp.train.TrainCodeResp;
import com.train.system.resp.train.TrainDetailResp;
import com.train.system.resp.train.TrainListResp;
import com.train.system.resp.train.TrainPageResp;
import com.train.system.bo.TrainCarriageBO;
import com.train.system.bo.TrainSeatBO;
import com.train.system.dto.seat.TrainGenerateSeatDTO;
import com.train.system.dto.seat.TrainSeatDTO;
import com.train.system.dto.train.TrainAddOrEditDTO;
import com.train.system.dto.train.TrainCodeDTO;
import com.train.system.dto.train.TrainPageDTO;
import com.train.system.mapper.TrainMapper;
import com.train.system.po.TrainPO;
import com.train.system.service.TrainCarriageService;
import com.train.system.service.TrainSeatService;
import com.train.system.service.TrainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author baitiaojun
 * @description 针对表【train(车次)】的数据库操作Service实现
 * @createDate 2025-02-20 01:04:22
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TrainServiceImpl extends ServiceImpl<TrainMapper, TrainPO>
    implements TrainService {

    //车次
    private final TrainMapper trainMapper;

    //车厢
    private final TrainCarriageService trainCarriageService;

    //座位
    private final TrainSeatService trainSeatService;

    //线程执行器
    private final ThreadPoolExecutor threadPoolExecutor;

    private final PlatformTransactionManager transactionManager;

    private final TransactionDefinition transactionDefinition;

    @Override
    public void addOrEditTrain(TrainAddOrEditDTO trainAddOrEditDTO) {
        //车次类型校验
        String type = trainAddOrEditDTO.getType();
        if (TrainTypeEnums.getByCode(type) == null) {
            throw new GlobalException(BizExceptionEnums.EXP_TRAIN_TYPE);
        }

        //如果是update, 校验id是否存在
        if (trainAddOrEditDTO.getId() != null) {
            Long id = trainMapper.getId(trainAddOrEditDTO.getCode());
            if (id == null) {
                throw new GlobalException(BizExceptionEnums.EXP_TRAIN_NOT_EXISTS);
            }

            //对于不同车次校验车次编号是否存在
            if (!trainAddOrEditDTO.getId().equals(id)) {
                if (trainMapper.existsCode(trainAddOrEditDTO.getCode())) {
                    throw new GlobalException(BizExceptionEnums.EXP_TRAIN_CODE_EXISTS);
                }
            }
        } else {
            //insert操作, 直接校验车次编号是否存在
            if (trainMapper.existsCode(trainAddOrEditDTO.getCode())) {
                throw new GlobalException(BizExceptionEnums.EXP_TRAIN_CODE_EXISTS);
            }
        }

        TrainPO trainPO = BeanUtil.copyProperties(trainAddOrEditDTO, TrainPO.class);
        boolean isSaved = this.saveOrUpdate(trainPO);
        if (!isSaved) {
            throw new GlobalException(BizExceptionEnums.EXP_ADD_TRAIN);
        }
    }

    @Override
    public PageResp<TrainPageResp> pageList(TrainPageDTO trainPageDTO) {
        return trainMapper.pageList(trainPageDTO);
    }

    @Override
    public void remove(Long id) {
        boolean isRemoved = this.removeById(id);
        if (!isRemoved) {
            throw new GlobalException(BizExceptionEnums.EXP_REMOVE_TRAIN);
        }
    }

    @Override
    public PageResp<TrainCodeResp> pageCodeList(TrainCodeDTO trainCodeDTO) {
        return trainMapper.pageCodeList(trainCodeDTO);
    }

    @Override
    public void generateTrainSeat(TrainGenerateSeatDTO trainGenerateSeatDTO) {
        String trainCode = trainGenerateSeatDTO.getTrainCode();

        //根据车次编号获取车厢
        List<TrainCarriageBO> trainCarriageList = trainCarriageService.getTrainCarriageList(trainCode);

        //所有车厢座位数
        List<TrainSeatBO> trainCarriageSeatList = new ArrayList<>();

        //遍历车厢获取每个车厢座位行、车厢等级
        for (TrainCarriageBO trainCarriageBO : trainCarriageList) {
            Integer rowCount = trainCarriageBO.getRowCount();
            String seatType = trainCarriageBO.getSeatType();

            //创建每个车厢的座位数量
            List<TrainSeatBO> trainSeatList = new ArrayList<>();

            //每趟车厢的座位序号
            int seatIndex = 1;

            //根据车厢等级获取每一行的座位列数
            SeatColEnums[] seatColList = SeatColEnums.getByType(seatType);

            //遍历每趟车厢座位行
            for (int i = 1; i <= rowCount; i++) {
                TrainSeatBO trainSeatBO;

                //遍历每行列数
                for (SeatColEnums seatColEnum : seatColList) {
                    //创建座位对象
                    trainSeatBO = new TrainSeatBO();
                    trainSeatBO.setCol(seatColEnum.getCode());
                    trainSeatBO.setRow(String.format("%02d", i));
                    trainSeatBO.setSeatType(seatType);
                    trainSeatBO.setTrainCode(trainCode);
                    trainSeatBO.setCarriageIndex(trainCarriageBO.getIndex());
                    trainSeatBO.setCarriageSeatIndex(seatIndex++);
                    trainSeatList.add(trainSeatBO);
                }
            }

            trainCarriageSeatList.addAll(trainSeatList);
        }

        List<TrainSeatDTO> trainSeatDTOList = BeanUtil.copyToList(trainCarriageSeatList, TrainSeatDTO.class);

        //异步执行sql添加操作, 定时任务自动更新执行状态
        threadPoolExecutor.execute(() -> {
            TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
            try {
                //查询该车次座位是否存在, 存在就执行座位删除操作
                if (trainSeatService.existsSeatByTrainCode(trainCode)) {

                    //删除车次的座位信息
                    trainSeatService.removeSeatByTrainCode(trainCode);
                }

                //添加车次的座位信息
                trainSeatService.saveBatchTrainSeat(trainSeatDTOList);
                transactionManager.commit(transaction);
            } catch (Exception e) {
                transactionManager.rollback(transaction);
                log.error("车次座位信息生成失败, 车次:{}, 原因:{}", trainCode, ExceptionUtils.getExpMsg(e));
            }
        });
    }

    @Override
    public TrainDetailResp getTrainDetail(String trainCode) {
        return trainMapper.getTrainDetail(trainCode.trim());
    }

    @Override
    public List<TrainPageResp> getTrainList(TrainPageDTO trainPageDTO) {
        return trainMapper.selectTrainList(trainPageDTO);
    }

    @Override
    public void validTrainCode(String trainCode) {
        if (!trainMapper.existsCode(trainCode)) {
            throw new GlobalException(BizExceptionEnums.EXP_TRAIN_CODE_NOT_EXISTS);
        }
    }

    @Override
    public List<TrainListResp> getTrainListByTrainCodes(List<String> trainCodes) {
        return trainMapper.selectTrainListByTrainCodes(trainCodes);
    }
}




